iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0
自我挑戰組

laravel+vue 學習系列 第 25

Day25. 前台 API 與頁面之四 (Vuex 與 Vue 路由)

  • 分享至 

  • xImage
  •  

一、選單 API

  1. 全站分類內容新增是否顯示於前台選單欄位, 提供 API 判斷是否要顯示
    https://ithelp.ithome.com.tw/upload/images/20220930/20128127YW7OsZpFrb.png

  2. 建立 API 資源

  • 新增路由
    // routes/api.php
    // 前台選單
    Route::get('/menu', 
                [
                    \App\Http\Controllers\Api\FrontController::class, 
                    'mainMenu'
                ]
              )->name('menu');
  • 新增 Controller function 回傳選單內容
    // App\Http\Controllers\Api\FrontController.php
    public function mainMenu() {
        
        $category = app(\App\Models\Categroy::class);
        $data = $category
                ->select(
                    [
                        'id', 
                        'parent_id', 
                        'name', 
                        'order', 
                        'display'
                    ])->where('display', '1')
                    ->where('parent_id', '0')
                    ->orderBy('order')->get();
        
        $menu = [];
        foreach( $data as $k => $c ) {
            // 父類別
            $menu[$k] = $c;
            
            // 子類別
            if( $category->where('parent_id', $c->id)
                        ->where('display', '1')
                        ->count() > 0 ) {
                $childens = [];
                $childen = $category->select(
                        [
                            'id', 
                            'parent_id', 
                            'name', 
                            'order', 
                            'display'
                        ])->where('parent_id', $c->id)
                        ->where('display', '1')
                        ->orderBy('order')
                        ->get();
                        
                foreach( $childen as $c_k => $c_c ) {
                    $childens[] = $c_c;                    
                }
                $menu[$k]->childen = $childens;
                $menu[$k]->childen_cnt = count($childens);
            }
        }

        $state = 0;
        if (count($menu)) $state = 1;
        
        return response()->json(['data' => $menu, 'state' => $state]);
    }

二、 前台 Vuex 請求選單 API

  1. Veux 生命週期

    • component 內可以使用 this.$store.dispatch({actions 的方法}) , 調用 actions function
    • actions function 會接收兩個參數
      • 第一個為參數為 Vue Component 本身的實例
      • 第二個參數為要修改的值
      • 此時可以呼叫 API 取回選單資料
      • 當處理好資料後會使用 Vue Component 本身 commit() 方法調用 mutations 內的對應方法
    • mutations function 會接受兩個參數
      • 第一個為 state 是 Vuex 用來存取資料的地方
      • 第二的為傳遞進來要修改的資料內容
      • 此時就會對 state 內的欄位進行修改
    • state
      • 若頁面上有綁定資料, 就會更新重新載入最新內容
  2. 製作 Vuex 模塊

    • 為了方便管理, 將每個功能拆成單一個模塊
    • resources/js/src/store 下新增 menu.js 檔案
        export default {
            namespaced:true, // 啟動命名
            // 設定 actions 提供 component 觸發
            actions:{    
                getMenu(context, value) {
                    console.log('menu actions start')
    
                    let url = '/api/menu'
                    axios.get(url).then(
                        response => {
                            //console.log(response.data.data)
                            let menu = response.data.data
                            // 更新選單內容
                            context.commit('GETMENU', menu)
                        },
                        error => {
                            console.log('menu action error', error)
                        }
                    )
                }    
            },
            mutations:{   
                GETMENU(state, data) {
                    state.meun_data = data
                }     
            },
            state:{      
                // 選單預設值
                meun_data: {}
            },
            getters:{   
            }
        }
    
    • Vuex 設定檔 resources/js/src/store/index.js 載入模塊
        import Vue from 'vue'
        // 引入Vuex
        import Vuex from 'vuex'
        // Vue 使用插件 Vuex
        Vue.use(Vuex)
    
        import Menu from './menu.js'
    
        // 新建一個 Vuex 實例
        export default new Vuex.Store({
            // 載入模塊
            modules: {
                Menu
            }
        })
    
    • 在 resources/js/components/main/menuComponent.vue 掛載完成後觸發 actions 取回選單資料
        <script>
            import {mapState, mapGetters} from 'vuex'
            export default {
                computed:{
                    // 利用 mapState 建立 Vue 計算屬性
                    // 要引入 mapState 才可以使用
                    ...mapState('Menu', ['meun_data'])
                },
                mounted() {
                    // 當 components 掛載完畢後調用 actions 方法
                    // Menu/getMenu 為 {模塊名稱}/{模塊 actions 方法)
                    this.$store.dispatch('Menu/getMenu')
                }
            }
        </script>
    
    • 使用 Vue.js devtools 查看
      https://ithelp.ithome.com.tw/upload/images/20220930/20128127CCvx1bjDvw.png

    • 開發工具查看是否有呼叫 API
      https://ithelp.ithome.com.tw/upload/images/20220930/20128127uOrBIRxbBG.png

三、前台選單套版

  1. 在 resources/js/components/main/menuComponent.vue 使用計算屬性 meun_data 建立選單 html
    <ul>
        <li v-for="(menu) in meun_data" :key="menu.id">
            <!-- 判斷是否有子選單 -->
            <template v-if="!menu.childen_cnt">
                <a href="#" target="_blank">{{ menu.name }}</a>
                <router-link :to="{path: '/category/'+menu.id}">{{ menu.name }}</router-link>
            </template>
            <template v-else>
                <!-- 子選單、下拉選單 -->
                <a class="dropdown-toggle" 
                    data-toggle="dropdown" 
                    data-target="#" 
                    href="javascript:;"
                >
                    {{ menu.name }}
                </a>
                <ul class="dropdown-menu">
                    <li v-for="(sub_menu) in menu.childen" :key="sub_menu.id">
                        <router-link :to="{path: '/category/'+sub_menu.id}">
                            {{ sub_menu.name }}
                        </router-link>
                    </li>
                </ul>
            </template>
        </li>        
    </ul>
  • 頁面畫面
    https://ithelp.ithome.com.tw/upload/images/20220930/20128127aNWFgaZIim.png

四、設定前台路由

  1. resources/js/scr/router/index.js 內設定網站路由
    import Vue from 'vue'
    // 引入 router 插件
    import VueRouter from 'vue-router'
    Vue.use(VueRouter)

    // 引入 Components
    import indexComponent from '../../components/pages/indexComponent'
    import categoryComponent from '../../components/pages/categoryComponent'
    import searchComponent from '../../components/pages/searchComponent'
    import articleComponent from '../../components/pages/articleComponent'
    import productComponent from '../../components/pages/productComponent'
    import userComponent from '../../components/pages/userComponent'
    import cartComponent from '../../components/pages/cartComponent'
    import payComponent from '../../components/pages/payComponent'

    export default new VueRouter({
        mode:'history',
        routes:[
            {
                path: '/',
                component: indexComponent
            },
            {
                // :category 為接受的參數
                // 可在頁面上使用 $route.params.category 取得
                path: '/category/:category', 
                component: categoryComponent
            },
            {
                path: '/category/:category/page/:page',
                component: categoryComponent
            },
            {
                path: '/search/:search',
                component: searchComponent
            },
            {
                path: '/article/:article',
                component: articleComponent
            },
            {
                path: '/product/:product',
                component: productComponent
            },
            {
                path: '/user/:user',
                component: userComponent
            },
            {
                path: '/user/cart/:user',
                component: cartComponent
            },
            {
                path: '/user/pay/:user',
                component: payComponent
            }

        ]
    })
  • 測試一下, 點選商品選單下的食品連結, 頁面中有成功顯示該類別 id
    https://ithelp.ithome.com.tw/upload/images/20220930/20128127lhdlGJgKOW.png

github 進版
剩下的明天繼續


上一篇
Day24. 前台 API 與頁面之三 (前台靜態頁面)
下一篇
Day26. 前台 API 與頁面之五 ( 切割頁面區塊 )
系列文
laravel+vue 學習32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言